#include <libpmemobj++/allocator.hpp>
#include <mutex>

class PMemAllocator {
    public:
        static PMemAllocator& get() {
            static std::once_flag flag;
            std::call_once(flag, []{ instance(); }); //匿名函数
            //mutex中，只调用一次
            return instance();
        }

        void allocate(PMEMoid* pmem_ptr, size_t size) {
            auto ctor = [](PMEMobjpool* pool, void* ptr, void* arg) { return 0; };
            int ret = pmemobj_alloc(pmem_pool_.handle(), pmem_ptr, size, 0, ctor, nullptr);
            if (ret != 0) {
                throw std::runtime_error{std::string("Could not allocate! ") + std::strerror(errno)};
            }
        }

        static PMemAllocator& instance() {
            static PMemAllocator instance{};
            return instance;
        }

        PMemAllocator() {
            pool_is_open_ = false;
            initialize();
        }

        void initialize() {
            destroy();

            int sds_write_value = 0;
            pmemobj_ctl_set(NULL, "sds.at_create", &sds_write_value);
            pmem_pool_ = pmem::obj::pool_base::create(CCEH_PMEM_POOL_FILE, "", 10ul * (1024l * 1024 * 1024), S_IRWXU);
            if (pmem_pool_.handle() == nullptr) {
                throw std::runtime_error("Could not open allocator pool file.");
            }
            pool_is_open_ = true;
        }

        void destroy() {
            if (pool_is_open_) {
                pmem_pool_.close();
                pool_is_open_ = false;
            }
            pmempool_rm(CCEH_PMEM_POOL_FILE, PMEMPOOL_RM_FORCE);
        }

        ~PMemAllocator() {
            destroy();
        }

        pmem::obj::pool_base pmem_pool_;
        bool pool_is_open_;
};

int main() {
    PMEMoid ret;
    PMemAllocator::get().allocate(&ret, size);
    //pmemobj_direct(ret)
    return 0;
}